home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_300 / 333_02 / awktab.y < prev    next >
Text File  |  1989-02-18  |  30KB  |  1,293 lines

  1.  
  2. /***************************************************************************/
  3. /*            gawk -- GNU version of awk               */
  4. /*         YACC input file to create the gAWK semantic parser        */
  5. /*                                       */
  6. /*         Copyright (C) 1986 Free Software Foundation           */
  7. /*             Written by Paul Rubin, August 1986            */
  8. /*                                       */
  9. /***************************************************************************/
  10. /*                                       */
  11. /* GAWK is distributed in the hope that it will be useful, but WITHOUT ANY */
  12. /* WARRANTY.  No author or distributor accepts responsibility to anyone    */
  13. /* for the consequences of using it or for whether it serves any       */
  14. /* particular purpose or works at all, unless he says so in writing.       */
  15. /* Refer to the GAWK General Public License for full details.           */
  16. /*                                       */
  17. /* Everyone is granted permission to copy, modify and redistribute GAWK,   */
  18. /* but only under the conditions described in the GAWK General Public       */
  19. /* License.  A copy of this license is supposed to have been given to you  */
  20. /* along with GAWK so you can know your rights and responsibilities.  It   */
  21. /* should be in a file named COPYING.  Among other things, the copyright   */
  22. /* notice and this notice must be preserved on all copies.           */
  23. /*                                       */
  24. /* In other words, go ahead and share GAWK, but don't try to stop          */
  25. /* anyone else from sharing it farther.  Help stamp out software hoarding! */
  26. /*                                       */
  27. /***************************************************************************/
  28.  
  29.  
  30. %{
  31. #define YYDEBUG 12
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <stdarg.h>
  36. #include <string.h>
  37. #include "awk.h"
  38.  
  39. STATIC int      NEAR PASCAL     yylex(void);
  40. STATIC int      NEAR PASCAL     parse_escape(char **string_ptr);
  41.  
  42.  
  43. /* The following variable is used for a very sickening thing.  The awk      */
  44. /* language uses white space as the string concatenation operator, but      */
  45. /* having a white space token that would have to appear everywhere in all */
  46. /* the grammar rules would be unbearable.  It turns out we can return      */
  47. /* CONCAT_OP exactly when there really is one, just from knowing what      */
  48. /* kinds of other tokens it can appear between (namely, constants,      */
  49. /* variables, or close parentheses).  This is because concatenation has   */
  50. /* the lowest priority of all operators.  want_concat_token is used to      */
  51. /* remember that something that could be the left side of a concat has      */
  52. /* just been returned.    If anyone knows a cleaner way to do this (don't   */
  53. /* look at the Un*x code to find one, though), please suggest it.      */
  54.  
  55. static int          want_concat_token;
  56.  
  57. /* Two more horrible kludges.  The same comment applies to these two too  */
  58.  
  59. static int          want_regexp     = 0; /* lexical scanning kludge   */
  60.  
  61. int              lineno = 1;         /* JF for error msgs      */
  62.  
  63. /* During parsing of a gAWK program, the pointer to the next character      */
  64. /* is in this variable.                           */
  65.  
  66. char             *lexptr;
  67. char             *lexptr_begin;
  68.  
  69. %}
  70.  
  71. %union
  72. {
  73.     long      lval;
  74.     AWKNUM      fval;
  75.     NODE     *nodeval;
  76.     int       nodetypeval;
  77.     char     *sval;
  78.     NODE    *(PASCAL *ptrval)(NODE *);
  79. }
  80.  
  81. %type <nodeval> exp start program rule pattern conditional regexp
  82. %type <nodeval> action variable redirect_in redirect_out exp_list builtin
  83. %type <nodeval> statements statement if_statement opt_exp
  84. %type <nodetypeval> whitespace relop
  85.  
  86. %token <sval> NAME REGEXP YSTRING
  87. %token <lval> ERROR INCDEC
  88. %token <fval> NUMBER
  89. %token <nodetypeval> ASSIGNOP MATCHOP NEWLINE CONCAT_OP
  90. %token <nodetypeval> LEX_BEGIN LEX_END LEX_IF LEX_ELSE
  91. %token <nodetypeval> LEX_WHILE LEX_FOR LEX_BREAK LEX_CONTINUE LEX_DELETE
  92. %token <nodetypeval> LEX_PRINT LEX_PRINTF LEX_NEXT LEX_EXIT
  93. %token <nodetypeval> RELOP_EQ RELOP_GEQ RELOP_LEQ RELOP_NEQ REDIR_APPEND
  94. %token  LEX_IN
  95. %token <lval> LEX_AND LEX_OR INCREMENT DECREMENT
  96. %token <ptrval> LEX_BUILTIN LEX_MATCH_FUNC LEX_SUB_FUNC LEX_SPLIT_FUNC
  97. %token <ptrval> LEX_GETLINE
  98.  
  99.  
  100. /* Lowest to highest */
  101. %right ASSIGNOP
  102. %left ','
  103. %right '?' ':'
  104. %left LEX_OR
  105. %left LEX_AND
  106. %left CONCAT_OP
  107. %nonassoc MATCHOP '>' '<' RELOP_EQ RELOP_GEQ RELOP_LEQ RELOP_NEQ
  108. %left '+' '-'
  109. %left '*' '/' '%'
  110. %right UNARY
  111. %right '^'
  112.  
  113. %%
  114.  
  115. start    : optional_newlines program
  116.       {
  117.           expression_value = $2;
  118.       }
  119.     ;
  120.  
  121.  
  122. program    : rule
  123.       {
  124.           $$ = node($1, NODE_RULE_LIST, NULL);
  125.       }
  126.  
  127.     | program rule
  128.       {           /* cons the rule onto the tail of list */
  129.           $$ = append_right($1, node($2, NODE_RULE_LIST, NULL));
  130.       }
  131.     ;
  132.  
  133. rule    : pattern action NEWLINE optional_newlines
  134.       {
  135.           $$ = node($1, NODE_RULE_NODE, $2);
  136.       }
  137.     ;
  138.  
  139.  
  140. pattern    : /* empty */
  141.       {
  142.           $$ = NULL;
  143.       }
  144.  
  145.     | LEX_BEGIN
  146.       {
  147.           $$ = node(NULL, NODE_K_BEGIN, NULL);
  148.       }
  149.  
  150.     | LEX_END
  151.       {
  152.           $$ = node(NULL, NODE_K_END, NULL);
  153.       }
  154.     | conditional
  155.       {
  156.           $$ = $1;
  157.       }
  158.  
  159.     | conditional ',' conditional
  160.       {
  161.           $$ = mkrangenode(node($1, NODE_COND_PAIR, $3));
  162.       }
  163.     ;
  164.  
  165.  
  166. conditional :
  167.       '!' conditional    %prec UNARY
  168.       {
  169.           $$ = node($2, NODE_NOT, NULL);
  170.       }
  171.  
  172.     | '(' exp_list ')' CONCAT_OP LEX_IN NAME
  173.       {
  174.           $$ = node(variable($6), NODE_MEMBER_COND, $2);
  175.       }
  176.  
  177.     | exp CONCAT_OP LEX_IN NAME
  178.       {
  179.           $$ = node(variable($4), NODE_MEMBER_COND, $1);
  180.       }
  181.  
  182.     | conditional LEX_AND conditional
  183.       {
  184.           $$ = node($1, NODE_AND, $3);
  185.       }
  186.  
  187.     | conditional LEX_OR conditional
  188.       {
  189.           $$ = node ($1, NODE_OR, $3);
  190.       }
  191.  
  192.     | '(' conditional ')'
  193.       {
  194.           $$ = $2;
  195.           want_concat_token = 0;
  196.       }
  197.  
  198.     | regexp
  199.       {
  200.           $$ = $1;
  201.       }
  202.  
  203.     | exp MATCHOP regexp
  204.       {
  205.           $$ = node($1, $2, $3);
  206.       }
  207.  
  208.     | exp MATCHOP variable
  209.       {
  210.           $$ = node($1, $2, $3);
  211.       }
  212.  
  213.     | exp relop exp
  214.       {
  215.           $$ = node($1, $2, $3);
  216.       }
  217.     ;
  218.  
  219. action    : /* empty */
  220.       {
  221.           $$ = NULL;
  222.       }
  223.  
  224.     | '{' whitespace statements '}'
  225.       {
  226.           $$ = $3;
  227.       }
  228.     ;
  229.  
  230.  
  231. statements :
  232.       statement
  233.       {
  234.           $$ = node($1, NODE_STATEMENT_LIST, NULL);
  235.       }
  236.  
  237.     | statements statement
  238.       {
  239.           $$ = append_right($1, node($2, NODE_STATEMENT_LIST, NULL));
  240.       }
  241.     ;
  242.  
  243. statement_term :
  244.       NEWLINE optional_newlines
  245.       {
  246.           $<nodetypeval>$ = NODE_ILLEGAL;
  247.       }
  248.  
  249.     | ';' optional_newlines
  250.       {
  251.           $<nodetypeval>$ = NODE_ILLEGAL;
  252.       }
  253.     ;
  254.  
  255. regexp    : '/'
  256.       {
  257.           ++want_regexp;
  258.       }
  259.       REGEXP '/'
  260.       {
  261.           want_regexp = 0;
  262.           $$ = node(NULL, NODE_REGEXP, (NODE *) make_regexp($3));
  263.       }
  264.  
  265. relop    : '>'
  266.       {
  267.           $$ = NODE_GREATER;
  268.       }
  269.     | '<'
  270.       {
  271.           $$ = NODE_LESS;
  272.       }
  273.     | RELOP_EQ
  274.       {
  275.           $$ = NODE_EQUAL;
  276.       }
  277.     | RELOP_GEQ
  278.       {
  279.           $$ = NODE_GEQ;
  280.       }
  281.     | RELOP_LEQ
  282.       {
  283.           $$ = NODE_LEQ;
  284.       }
  285.     | RELOP_NEQ
  286.       {
  287.           $$ = NODE_NOTEQUAL;
  288.       }
  289.     ;
  290.  
  291. whitespace :
  292.       /* blank */
  293.       {
  294.           $$ = NODE_ILLEGAL;
  295.       }
  296.  
  297.     | CONCAT_OP
  298.     | NEWLINE
  299.     | whitespace CONCAT_OP
  300.     | whitespace NEWLINE
  301.     ;
  302.  
  303. statement :
  304.       '{' whitespace statements '}' whitespace
  305.       {
  306.           $$ = $3;
  307.       }
  308.  
  309.     | if_statement
  310.       {
  311.           $$ = $1;
  312.       }
  313.  
  314.     | LEX_WHILE '(' conditional ')' whitespace statement
  315.       {
  316.           $$ = node($3, NODE_K_WHILE, $6);
  317.       }
  318.  
  319.     | LEX_FOR '(' opt_exp ';' conditional ';' opt_exp ')' whitespace statement
  320.       {
  321.           $$ = node($10, NODE_K_FOR, (NODE *) make_for_loop($3, $5, $7));
  322.       }
  323.  
  324.     | LEX_FOR '(' opt_exp ';' ';' opt_exp ')' whitespace statement
  325.       {
  326.           $$ = node($9, NODE_K_FOR,
  327.             (NODE *) make_for_loop($3, NULL, $6));
  328.       }
  329.  
  330.     | LEX_FOR '(' NAME CONCAT_OP LEX_IN NAME ')' whitespace statement
  331.       {
  332.           $$ = node($9, NODE_K_ARRAYFOR,
  333.             (NODE *) make_for_loop(variable($3),
  334.                            NULL, variable($6)));
  335.       }
  336.  
  337.     | LEX_BREAK statement_term
  338.       /* for break, maybe we'll have to remember where to break to */
  339.       {
  340.           $$ = node(NULL, NODE_K_BREAK, NULL);
  341.       }
  342.  
  343.     | LEX_CONTINUE statement_term
  344.       /* similarly */
  345.       {
  346.           $$ = node(NULL, NODE_K_CONTINUE, NULL);
  347.       }
  348.  
  349.     | LEX_PRINT exp_list redirect_out statement_term
  350.       {
  351.           $$ = node($2, NODE_K_PRINT, $3);
  352.       }
  353.  
  354.     | LEX_PRINT '(' exp_list ')'          /* BW: print(...) */
  355.       {
  356.